<?php

class DeliveryCalculator
{

	protected $_data;

	/** @var City */
	protected $_city;

	protected $_result;

	public function __construct($data)
	{
		$this->_data = $data;
		$this->_city = $data['city_id'] ? CityTable::getInstance()->findOneById($data['city_id']) : null;
	}

        /**
         * @param <type> $total
         * @param <type> $per_basket if set to true, returns total sum per basket, else returns grand total
         * @param <type> $no_delivery if set to true, returns 0
         * @return array delivery fees for every item in basket
         */
	public function calculate($total = false, $per_basket = false, $no_delivery = false)
	{
		if ($no_delivery) return 0;
		$this->_result = array();
		foreach ($this->_data['baskets'] as $basket)
		{
			$this->_result[$basket->getId()] = $this->calculate_basket($basket);
		}

		return $total ? $this->get_total($per_basket) : $this->_result;
	}

	public function get_total($per_basket = false)
	{
		$result = $this->_result;
		$total = 0;
		$totals = array();
		foreach ($result as $bid => $basket)
		{
			$totals[$bid] = 0;
			foreach ($basket['basket']['rules'] as $key => $val)
			{
				$total += $val;
				$totals[$bid] += $val;
			}
			foreach ($basket['basket']['items'] as $key => $prop)
			{
				foreach ($prop as $key => $val)
				{
					$total += $val;
					$totals[$bid] += $val;
				}
			}

		}

		return $per_basket ? $totals : $total;
	}

        /**
         * calculates delivery fees for specific basket
         * @param Basket $basket
         * @return array
         */
	public function calculate_basket(Basket $basket)
	{
		$result['basket'] = $this->getDeliveryRule('shop', $basket->shop_id)->apply($basket);

		foreach ($basket->Items as $bi_key => $bitem)
		{
			if (($product_dr = $this->getDeliveryRule('product', $bitem->product_id)) && !$product_dr->isNew())  //Todo: find out what method isNew() does
			{
//				die($product_dr->isNew() ? 'NEW' : 'OLD');
				$result['items'][$bitem->getId()] = $product_dr->apply($bitem);
			}
		}

		return $result;
	}
	/**
	 *
	 * @param string $item_type
	 * @param int $item_id
	 * @return DeliveryRule
	 */
	public function getDeliveryRule($item_type, $item_id)
	{
		return DeliveryRuleTable::getInstance()->getDeliveryRule($item_type, $item_id, $this->_city, $this->_data['delivery']);
	}

	/**
	 * if Product defines its own DeliveryRules, those are used insted of shop DeliveryRules
	 * in future we colud implement more complex logic for rule overriding
	 * 
	 * @param Doctrine_Collection $shop_drs
	 * @param Doctrine_Collection $product_drs
	 *
	 * @return Doctrine_Collection
	 */
	public function combineDeliveryRules($shop_dr, $product_dr)
	{
		return $product_dr->isNew() ? $shop_dr : $product_dr;
	}

	public static function getNullDeliveryData()
	{
		return array
		(
			'city_id'=>null,
			'delivery' => array
			(
				'da_id'=>null,
				'dm_class_id'=>null,
				'pm_class_id'=>null
			)
		);
	}

}

?>
